package com.ctsi.commons.event.config;

import com.ctsi.commons.util.UtilMisc;
import com.ctsi.commons.util.UtilXml;
import com.ctsi.commons.util.module.ModuleLoad;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 配置文件转化为对象
 * 
 * @author zhangjw
 * 
 */
public class EventConfigReader {
	private static final Logger log = LoggerFactory.getLogger(EventConfigReader.class);

	public static final String configFileName = "eventConfig.xml";

	public static List<EventModule> readEventConfig() {
		final long s = System.currentTimeMillis();
		List<EventModule> result = new ArrayList<EventModule>();

		try {
			List<URL> uList = ModuleLoad.load(null, configFileName);
			for (URL url : uList) {
				EventModule ec = readOne(url,true);
				if (ec != null) {
					if (log.isWarnEnabled()) {
						if (result.contains(ec)) {
							log.warn("duplicate EventModule id:{}  EventModule :{}", url,ec);
						}
					}
					result.add(ec);
				}
			}
		} catch (Exception e) {
			log.error(e.toString());
			throw new RuntimeException(e);
		}
		log.debug("readEventConfig use {} time", System.currentTimeMillis() - s);
		return result;
	}

	public static List<EventModule> readEventConfigNoCheck() {
		List<EventModule> result = new ArrayList<EventModule>();

		try {
			List<URL> uList = ModuleLoad.load(null, configFileName);
			for (URL url : uList) {
				EventModule ec = readOne(url,false);
				if (ec != null) {
					if (log.isWarnEnabled()) {
						if (result.contains(ec)) {
							log.warn("duplicate EventModule id:{} EventModule :{} ", url,ec);
						}
					}
					result.add(ec);
				}
			}
		} catch (Exception e) {
			log.error(e.toString());
			throw new RuntimeException(e);
		}
		return result;
	}

	private static EventModule readOne(Element root) throws SAXException, ParserConfigurationException, IOException {
		String moduleId = root.getAttribute("moduleId");
		String moduleName = root.getAttribute("moduleName");
		EventModule ec = new EventModule(moduleId, moduleName);
		log.debug("moduleId:{}  moduleName:{} ",moduleId,moduleName);
		ec.setEnable(UtilMisc.checkBoolean(root.getAttribute("active"),true));

		// NodeList nl = root.getChildNodes();
		List<? extends Element> nl = UtilXml.childElementList(root, "event");
		for (int i = 0; i < nl.size(); i++) {
			Node eNode = nl.get(i);
			ec.addEvent(createEvent(eNode));
		}
		Element eventSrc = UtilXml.firstChildElement(root, "publishevents");
		if (eventSrc != null) {
			List<? extends Element> eventSrcList = UtilXml.childElementList(eventSrc, "publishevent");
			for (int i = 0; i < eventSrcList.size(); i++) {
				Element eNode = eventSrcList.get(i);
				EventSource es = createEventSource(eNode);
				if (!ec.contains(es)) {
					ec.addEventSource(es);
				} else {
					log.warn("one module {} publish duplicat event {}", moduleId, es.getEventId());
				}
			}
		}
		return ec;
	}

	private static EventSource createEventSource(Element eNode) {
		EventSource es = new EventSource();
		es.setDescription(eNode.getAttribute("description"));
		es.setEventId(eNode.getAttribute("eventId"));
		return es;
	}

	private static EventModule readOne(URL url,boolean check) throws SAXException, ParserConfigurationException, IOException {
		Document doc = UtilXml.readXmlDocument(url,true);
		Element root = doc.getDocumentElement();
		if (check && !"true".equals(root.getAttribute("active"))) {
			log.info("config :{}  moduleName:{} is inactive",url, root.getAttribute("moduleName"));
			return null;
		}
		return readOne(root);

	}



	private static Event createEvent(Node eNode) {
		Event result = new Event();
		Map<String, String> aList = UtilXml.attributesToMap(eNode);
		result.setClassKey(aList.get("classKey"));
		Element con = UtilXml.firstChildElement((Element) eNode, "condition");
		result.setCondition(UtilXml.elementValue(con));
		result.setSync(UtilMisc.checkBoolean(aList.get("sync"), true));
		result.setEventid(aList.get("eventid"));
		result.setFac(aList.get("fac"));
		result.setName(aList.get("name"));
		result.setId(aList.get("id"));
		result.setScope(aList.get("scope"));
		result.setisEnable(aList.get("disable"));
		result.setSystemName(aList.get("systemName"));
		return result;
	}
}
